package crp.core.workflow.domain.repositories;

import com.qwlabs.lang.C2;
import com.qwlabs.lang.F2;
import com.qwlabs.panache.Where;
import crp.core.shared.CustomPanacheNativeQuery;
import crp.core.shared.Tables;
import crp.core.workflow.domain.models.WorkflowTaskEntity;
import crp.core.workflow.domain.models.WorkflowTaskStatus;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import io.quarkus.panache.common.Sort;

import javax.enterprise.context.ApplicationScoped;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Stream;

import static java.util.stream.Collectors.joining;

@ApplicationScoped
public class WorkflowTaskRepository implements PanacheRepositoryBase<WorkflowTaskEntity, String> {


    public PanacheQuery<WorkflowTaskEntity> findBy(Collection<String> candidates, Collection<String> instanceIds,
                                                   WorkflowTaskStatus taskStatus) {
        Where where = Where.create();
        Optional.ofNullable(taskStatus).ifPresent((s) -> {
            where.and("status=:taskStatus", "taskStatus", s.name());
        });

        C2.ifNotEmpty(candidates, () -> {
            where.and("candidates && CAST( :candidates AS character varying[])", "candidates",
                    candidates.stream().collect(joining(",", "{", "}")));
        });

        C2.ifNotEmpty(instanceIds, () -> {
            where.and("instance_id in :instanceIds", "instanceIds", instanceIds);
        });


        String dataQuery = String.format(" select * from %s %s", Tables.WORKFLOW_TASK, where.getWithWhere());
        String countQuery = String.format(" select count(*) from %s %s", Tables.WORKFLOW_TASK, where.getWithWhere());

        return new CustomPanacheNativeQuery<>(getEntityManager(), dataQuery, countQuery, where.getParameters(),
                WorkflowTaskEntity.class);
    }

    public Stream<WorkflowTaskEntity> byInstanceIds(Collection<String> instanceIds, WorkflowTaskStatus status) {
        if (C2.isEmpty(instanceIds)) {
            return Stream.empty();
        }
        Where where = Where.create().and("instance.id in :instanceIds", "instanceIds", instanceIds);
        F2.ifPresent(status, () -> {
            where.and("status=:status", "status", status);
        });
        return find(where.get(), Sort.descending("createdAt"), where.getParameters()).stream();
    }

    public Stream<WorkflowTaskEntity> byIds(Collection<String> ids) {
        if (C2.isEmpty(ids)) {
            return Stream.empty();
        }
        Where where = Where.create().and("id in :ids", "ids", ids);
        return find(where.get(), Sort.descending("createdAt"), where.getParameters()).stream();
    }
}
